package ace.tool.generate.code.impl.resolver.scheme;

import ace.tool.generate.code.impl.resolver.scheme.model.dto.EntityClassSchemeInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.dto.ProjectInfo;
import ace.tool.generate.code.impl.service.model.input.GenerateInput;
import ace.tool.generate.code.impl.service.model.input.GenerateModelInput;
import java.util.HashMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Builder;
import org.apache.commons.text.StringSubstitutor;

/**
 * @author caspar
 * @date 2023/11/17 10:34
 */
@Builder
@AllArgsConstructor
public class EntityClassSchemeInfoResolver {
  private final GenerateModelInput modelInput;
  private final GenerateInput input;
  private final ProjectInfo apiProjectInfo;
  private final ProjectInfo coreProjectInfo;
  private final ProjectInfo sdkProjectInfo;

  public EntityClassSchemeInfo resolve() {
    return EntityClassSchemeInfo.builder()
        .entityIdType(this.getEntityIdType())
        .entityClassName(this.getEntityClassName())
        .entityClassFullName(this.getEntityClassFullName())
        .entityClassLowercaseDashName(this.getEntityClassLowercaseDashName())
        .apiClassPackageFullName(this.getApiPackageFullName())
        .apiClassName(this.getApiClassName())
        .apiClassFullName(this.getApiClassFullName())
        .apiClassFileFullName(this.getApiClassFileFullName())
        .dtoClassPackageFullName(this.getDtoClassPackageFullName())
        .dtoClassName(this.getDtoClassName())
        .dtoClassFullName(this.getDtoClassFullName())
        .dtoClassFileFullName(this.getDtoClassFileFullName())
        .feignApiClassPackageFullName(this.getFeignApiClassPackageFullName())
        .feignApiClassName(this.getFeignApiClassName())
        .feignApiClassFullName(this.getFeignApiClassFullName())
        .feignApiClassFileFullName(this.getFeignApiClassFileFullName())
        .feignClassPackageFullName(this.getFeignClassPackageFullName())
        .feignClassName(this.getFeignClassName())
        .feignClassFullName(this.getFeignClassFullName())
        .feignClassFileFullName(this.getFeignClassFileFullName())
        .build();
  }

  private String getFeignClassFileFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("sourceCodeRootDir", sdkProjectInfo.getSourceCodeRootDir());
    data.put("classFullName", this.getFeignClassFullName().replace("\\.", "/"));
    return StringSubstitutor.replace("${sourceCodeRootDir}/${classFullName}.java", data);
  }

  private String getFeignClassFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("packageFullName", this.getFeignClassPackageFullName());
    data.put("className", this.getFeignClassName());
    return StringSubstitutor.replace("${packageFullName}.${className}", data);
  }

  private String getFeignClassPackageFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("rootPackageFullName", this.getRootPackageFullName());
    data.put("classPackagePrefix", input.getFeignClassPackagePrefix());
    return StringSubstitutor.replace("${rootPackageFullName}${classPackagePrefix}", data);
  }

  private String getFeignClassName() {
    Map<String, String> data = new HashMap<>();
    data.put("classNameSuffix", input.getFeignClassNameSuffix());
    data.put("entityClassName", this.getEntityClassName());
    return StringSubstitutor.replace("${entityClassName}${classNameSuffix}", data);
  }

  private String getFeignApiClassFileFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("sourceCodeRootDir", sdkProjectInfo.getSourceCodeRootDir());
    data.put("classFullName", this.getFeignApiClassFullName().replace("\\.", "/"));
    return StringSubstitutor.replace("${sourceCodeRootDir}/${classFullName}.java", data);
  }

  private String getFeignApiClassFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("packageFullName", this.getFeignApiClassPackageFullName());
    data.put("className", this.getFeignApiClassName());
    return StringSubstitutor.replace("${packageFullName}.${className}", data);
  }

  private String getFeignApiClassPackageFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("rootPackageFullName", this.getRootPackageFullName());
    data.put("classPackagePrefix", input.getFeignApiClassPackagePrefix());
    return StringSubstitutor.replace("${rootPackageFullName}${classPackagePrefix}", data);
  }

  private String getFeignApiClassName() {
    Map<String, String> data = new HashMap<>();
    data.put("classNameSuffix", input.getFeignApiClassNameSuffix());
    data.put("entityClassName", this.getEntityClassName());
    return StringSubstitutor.replace("${entityClassName}${classNameSuffix}", data);
  }

  private String getDtoClassFileFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("sourceCodeRootDir", apiProjectInfo.getSourceCodeRootDir());
    data.put("apiClassFullName", this.getDtoClassFullName().replace("\\.", "/"));
    return StringSubstitutor.replace("${sourceCodeRootDir}/${apiClassFullName}.java", data);
  }

  private String getDtoClassFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("packageFullName", this.getDtoClassPackageFullName());
    data.put("className", this.getDtoClassName());
    return StringSubstitutor.replace("${packageFullName}.${className}", data);
  }

  private String getDtoClassPackageFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("rootPackageFullName", this.getRootPackageFullName());
    data.put("classPackagePrefix", input.getDtoClassPackagePrefix());
    return StringSubstitutor.replace("${rootPackageFullName}${classPackagePrefix}", data);
  }

  private String getDtoClassName() {
    Map<String, String> data = new HashMap<>();
    data.put("classNameSuffix", input.getDtoClassNameSuffix());
    data.put("entityClassName", this.getEntityClassName());
    return StringSubstitutor.replace("${entityClassName}${classNameSuffix}", data);
  }

  private String getApiClassFileFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("sourceCodeRootDir", apiProjectInfo.getSourceCodeRootDir());
    data.put("apiClassFullName", this.getApiClassFullName().replace("\\.", "/"));
    return StringSubstitutor.replace("${sourceCodeRootDir}/${apiClassFullName}.java", data);
  }

  private String getApiPackageFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("rootPackageFullName", this.getRootPackageFullName());
    data.put("apiClassPackagePrefix", input.getApiClassPackagePrefix());
    return StringSubstitutor.replace("${rootPackageFullName}${apiClassPackagePrefix}", data);
  }

  private String getApiClassFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("apiPackageFullName", this.getApiPackageFullName());
    data.put("apiClassName", this.getApiClassName());
    return StringSubstitutor.replace("${apiPackageFullName}.${apiClassName}", data);
  }

  private String getApiClassName() {
    Map<String, String> data = new HashMap<>();
    data.put("apiClassNameSuffix", input.getApiClassNameSuffix());
    data.put("entityClassname", this.getEntityClassName());
    return StringSubstitutor.replace("${entityClassname}${apiClassNameSuffix}", data);
  }

  private String getRootPackageFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("codeNamespacePrefix", input.getProjectNamePrefix().replace("-", "."));
    data.put("codeNamespace", input.getProjectName().replace("-", "."));
    return StringSubstitutor.replace("${codeNamespacePrefix}.${codeNamespace}", data);
  }

  private String getEntityClassPackageFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("rootPackageFullName", this.getRootPackageFullName());
    data.put("entityClassPackagePrefix", input.getEntityClassPackagePrefix());
    return StringSubstitutor.replace("${rootPackageFullName}.${entityClassPackagePrefix}", data);
  }

  private String getEntityClassName() {
    return this.modelInput.getName();
  }

  private String getEntityClassFullName() {
    Map<String, String> data = new HashMap<>();
    data.put("entityClassPackageFullName", this.getEntityClassPackageFullName());
    data.put("entityClassName", this.getEntityClassName());
    return StringSubstitutor.replace("${entityClassPackageFullName}${entityClassName}", data);
  }

  private String getEntityIdType() {
    return this.modelInput.getFields().stream()
        .filter(p -> p.getIdFlag())
        .findFirst()
        .get()
        .getType()
        .getName();
  }

  /**
   * 小写破折号类名
   */
  private String getEntityClassLowercaseDashName() {
    return ace.cmp.util.CaseFormatUtils.convertUpperCamelToLowerUnderscore(this.getEntityClassName())
        .replaceAll("_", "-");
  }
}
